package ast;

import java.util.ArrayList;

import symbol.FuncParamsTypeList;
import symbol.astPreprocessContext;

public class FunctionSignature extends AstItem {
	public enum SignatureType {
		CLASS_CONSTRUCTOR, CLASS_METHOD, FUNC_DEF
	}

	public SignatureType signatureType;
	public String funcName;
	// DataSignature类
	public ArrayList<AstItem> parameters = new ArrayList<AstItem>();
	// DataSignature类
	public String returnType; // 返回值的变量名可以不填
	
	public String funckey; // 预处理时填上

	public String classBelonged; // 所属的类名
	
	public String toString() {
//		System.out.println(signatureType);
		if (signatureType == SignatureType.CLASS_CONSTRUCTOR) {
			returnType = classBelonged;
			funcName = classBelonged + "_constructor";
		}
		String result = "";
		// 类的方法和构造器要加上this参数
		// 记录一下强制转换类型的map(主要因为有数组)
		assert signatureType != null;
		String[] returnTypeInfo = returnType.split("_");
		assert returnTypeInfo.length > 0;
		String returnType_c = returnTypeInfo[0];
		if (returnTypeInfo[0].equals("bool")) returnType_c = "int";
		else if (returnTypeInfo[0].equals("longlong")) returnType_c = "long long";
		else if (returnTypeInfo[0].equals("string")) returnType_c = "char[]";
		else if (returnTypeInfo[0].contains("func")) returnType_c = "void *";
		else if (astPreprocessContext.getClassList().contains(returnTypeInfo[0])) returnType_c = "struct " + returnTypeInfo[0] + "*";
		if (returnTypeInfo.length == 2) {
			// 数组
			for (int i = 0;i < Integer.parseInt(returnTypeInfo[1]);i++) {
				returnType_c += "[]";
			}
		}
		
		// 如果没有重载(且不是类的构造器)，返回原函数名
		if (astPreprocessContext.isNoReload(funcName) && !funcName.contains("constructor")) result += returnType_c + " " + funcName + "(";
		// 否则用重载的重命名
		else result += returnType_c + " " + funckey + "(";
		
		if (signatureType == SignatureType.CLASS_METHOD) {
			// 类方法多加一个参数
			result += "struct " + classBelonged + "* this";
			if (parameters.size() > 0) result += ", ";
		}
		
		for (int i = 0;i < parameters.size();i++) {
			if (parameters.get(i) instanceof PrimaryDataSignature) {
				// 非数组
				result += ((PrimaryDataSignature) parameters.get(i)).getDeclString() + " " + parameters.get(i).toString();
				if (((PrimaryDataSignature) parameters.get(i)).dataType.equals("string")) {
					result += "[]";
				}
			} else {
				// 数组
				result += ((ComplexDataSignature) parameters.get(i)).toString();
			}
//			result += parameters.get(i).toString();
			if (i != parameters.size() - 1) result += ", ";
		}

		result += ") ";
		return result;
	}
	
	// TODO: 根据
	public void preprocess(AstItem father) {
		// 建立函数重载的映射，并新建函数变量表和符号表
		ArrayList<String> paramTypes = new ArrayList<String>();
		ArrayList<String> paramNames = new ArrayList<String>();
		for (int i = 0;i < parameters.size();i++) {
			AstItem param = parameters.get(i);
			assert (param instanceof PrimaryDataSignature) || (param instanceof ComplexDataSignature);
			if (param instanceof PrimaryDataSignature) {
				paramTypes.add(((PrimaryDataSignature) param).dataType);
				paramNames.add(((PrimaryDataSignature) param).name);
//				System.out.println(((PrimaryDataSignature) param).name);
			} else {
				// 数组参数
				assert ((ComplexDataSignature) param).dataOperated instanceof PrimaryDataSignature;
				// 函数形参类型仅区分数组维度
				Integer dimCount = ((ComplexDataSignature) param).operation.size();
				PrimaryDataSignature d = ((PrimaryDataSignature) ((ComplexDataSignature) param).dataOperated);
				paramTypes.add(d.dataType + "_" + dimCount.toString());
				paramNames.add(d.name);
			}
		}
		FuncParamsTypeList paramsTypeList = new FuncParamsTypeList(paramTypes, returnType);
		// TODO:如果是类构造器或者方法，需要另外处理
		if (signatureType == SignatureType.CLASS_CONSTRUCTOR) {
			astPreprocessContext.getContext();
			paramsTypeList = new FuncParamsTypeList(paramTypes, astPreprocessContext.getNowClass());
			// 类的构造器
			assert father instanceof ClassDef;
			String className = ((ClassDef) father).className;
			classBelonged = className;
			astPreprocessContext.getContext();
			// 记录函数重载
			astPreprocessContext.addFuncReload(className + "_constructor", paramsTypeList);
			// 建立函数变量记录表
			astPreprocessContext.createFuncTables(className + "_constructor", paramsTypeList);
			// 建立符号表，并把形参填进去
			astPreprocessContext.createSymbolTables(className + "_constructor", paramsTypeList, paramNames);
			funckey = "_" + className + "_constructor" + "_" + paramsTypeList.toString();
		} else if (signatureType == SignatureType.CLASS_METHOD) {
			// 类的方法
			assert father instanceof ClassDef;
			String className = ((ClassDef) father).className;
			classBelonged = className;
			astPreprocessContext.getContext();
			// 记录函数重载
			astPreprocessContext.addFuncReload(className + "_" + funcName, paramsTypeList);
			// 建立函数变量记录表
			astPreprocessContext.createFuncTables(className + "_" + funcName, paramsTypeList);
			// 建立符号表，并把形参填进去
			astPreprocessContext.createSymbolTables(className + "_" + funcName, paramsTypeList, paramNames);
			funckey = "_" + className + "_" + funcName + "_" + paramsTypeList.toString();
		} else {
			astPreprocessContext.getContext();
			// 记录函数重载
			astPreprocessContext.addFuncReload(funcName, paramsTypeList);
			// 建立函数变量记录表
			astPreprocessContext.createFuncTables(funcName, paramsTypeList);
			// 建立符号表，并把形参填进去
			astPreprocessContext.createSymbolTables(funcName, paramsTypeList, paramNames);
			funckey = "_" + funcName + "_" + paramsTypeList.toString();
		}
	}
	
	@Override
	public String toJsonString() {
		String json = "{";
		json += "\"Type\": \"FuncSignature\",";
		json += "\"SignatureType\": \"" + signatureType.toString() + "\",";
		json += "\"FuncName\": \"" + funcName + "\",";
		json += "\"Parameters\": [";
		for (AstItem astItem: parameters) {
			json += astItem.toJsonString() + ",";
		}
		json += "],";
		json += "\"ReturnType\": \"" + returnType + "\"";
		json += "}";
		return json;
	}
}
